package net.wexoo.onlinedivelog.view.pages.detail.user;

import static org.slf4j.LoggerFactory.getLogger;
import net.wexoo.onlinedivelog.entity.diveLevel.DiveLevelBean;
import net.wexoo.onlinedivelog.entity.diver.DiverBean;
import net.wexoo.onlinedivelog.entity.person.PersonBean;
import net.wexoo.onlinedivelog.proxy.diveLevel.IDiveLevelProxy;
import net.wexoo.onlinedivelog.proxy.diver.IDiverProxy;
import net.wexoo.onlinedivelog.proxy.person.IPersonProxy;
import net.wexoo.onlinedivelog.reusable.SameActionOnClickAjaxButton;
import net.wexoo.onlinedivelog.reusable.behaviour.AjaxCSSClassAppender;
import net.wexoo.onlinedivelog.reusable.model.ApostrophResourceModel;
import net.wexoo.onlinedivelog.reusable.page.WEXWebPage;
import net.wexoo.onlinedivelog.reusable.security.spam.Captcha;
import net.wexoo.onlinedivelog.view.util.DiveLogSession;
import net.wexoo.onlinedivelog.view.util.NotificationPanel;

import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.form.AjaxFormValidatingBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.PasswordTextField;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.validation.EqualPasswordInputValidator;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;
import org.apache.wicket.validation.validator.EmailAddressValidator;

public class UserDetailPage extends WEXWebPage {

	private static final long serialVersionUID = 1L;

	private NotificationPanel notificationPanel;
	private final Form<PersonBean> userForm;
	private WebMarkupContainer currentDivingSchoolContainer;

	private PersonBean personBean;
	private boolean existingPerson;
	private String repeatedPassword;
	private boolean registerDiver = true;
	private boolean registerDiveGuide;
	private String currentDivingSchool;

	@SpringBean
	private IDiveLevelProxy diveLevelProxy;
	@SpringBean
	private IPersonProxy personProxy;
	@SpringBean
	private IDiverProxy diverProxy;

	public UserDetailPage(PersonBean user) {
		super();

		personBean = user;
		if (personBean.getId() != null)
			existingPerson = true;

		buildNotificationPanel();

		// parent node
		userForm = new Form<PersonBean>("userForm", new CompoundPropertyModel<PersonBean>(personBean));
		add(userForm);

		buildRegisterButton();

		buildCancelButton();

		buildPersonalDataFields();

		buildDiveLevelChoice();

		buildLoginField();

		buildPasswordFields();

		buildDiverCheck();

		buildDiveGuideCheck();

		buildCurrentDivingSchoolContainer();

		buildCaptchaPanel();

		userForm.add(new AjaxFormValidatingBehavior(userForm, "onLoad"));

		userForm.visitChildren(FormComponent.class, new IVisitor<FormComponent<?>, Void>() {

			@Override
			public void component(FormComponent<?> formComponent, IVisit<Void> visit) {
				formComponent.add(new AjaxCSSClassAppender(notificationPanel));
				visit.dontGoDeeper();
			}
		});
	}

	private void buildNotificationPanel() {
		notificationPanel = new NotificationPanel("userPanelNotificationPanel");
		add(notificationPanel);
	}

	private void buildRegisterButton() {
		AjaxButton registerButton = new AjaxButton("registerButton") {

			private static final long serialVersionUID = 1L;

			@Override
			protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
				try {
					personBean = personProxy.saveOrUpdate(personBean);
					((DiveLogSession) getSession()).setLoggedInPerson(personBean);

					if (registerDiver) {
						DiverBean newDiver = new DiverBean(personBean);
						diverProxy.saveOrUpdate(newDiver);
						info("Diver checked");
					}
					if (registerDiveGuide)
						info("DiveGuide checked");

				} catch (Exception e) {
					System.out.println("Exception catch in save");
					getLogger(getClass()).error(e.toString());
					System.out.println("after log error to string");
					getLogger(getClass()).error(e.getMessage());
					System.out.println("after getLogger error get message");
					e.printStackTrace();
					System.out.println("after getLogger error get message");
					error(e.toString());
					notificationPanel.refresh(target);
				}
				info(personBean.getLogin() + new ResourceModel("successfullySaved"));
				getLogger(getClass()).info(personBean.getLogin() + new ResourceModel("successfullySaved"));
				notificationPanel.refresh(target);

				ModalWindow.closeCurrent(target);
			}

			@Override
			protected void onError(AjaxRequestTarget target, Form<?> form) {
				notificationPanel.refresh(target);
			}
		};
		userForm.add(registerButton);
	}

	private void buildCancelButton() {
		AjaxButton cancel = new SameActionOnClickAjaxButton("cancelButton") {
			private static final long serialVersionUID = 1L;

			@Override
			protected void doOnClickAction(AjaxRequestTarget target, Form<?> form) {
				ModalWindow.closeCurrent(target);
			}
		};
		userForm.add(cancel);
	}

	private void buildPersonalDataFields() {
		userForm.add(new RequiredTextField<String>("forename").setLabel(new ApostrophResourceModel("forenameLabel")));
		userForm.add(new RequiredTextField<String>("surname").setLabel(new ApostrophResourceModel("surnameLabel")));

		RequiredTextField<String> emailTextField = new RequiredTextField<String>("email");
		emailTextField.add(EmailAddressValidator.getInstance());
		setLabelOfComponent(emailTextField, "emailLabel");
		userForm.add(emailTextField);
	}

	private void buildDiveLevelChoice() {
		DropDownChoice<DiveLevelBean> diveLevelChoice = new DropDownChoice<DiveLevelBean>("diveLevelChoice",
				new PropertyModel<DiveLevelBean>(personBean, "diveLevel"), diveLevelProxy.getList(),
				new ChoiceRenderer<DiveLevelBean>("name", "id"));

		setLabelOfComponent(diveLevelChoice, "diveLevelLabel");
		diveLevelChoice.setRequired(true);
		userForm.add(diveLevelChoice);
	}

	private void buildLoginField() {
		final RequiredTextField<String> login = new RequiredTextField<String>("login");

		login.add(new AjaxFormComponentUpdatingBehavior("onchange") {

			private static final long serialVersionUID = 1L;

			@Override
			protected void onUpdate(AjaxRequestTarget target) {
			}
		});
		// login.add(new UsernameValidator());
		setLabelOfComponent(login, "loginLabel");

		userForm.add(login);
	}

	private void buildPasswordFields() {
		PasswordTextField password = new PasswordTextField("password");
		// password.add(new PasswordPolicyValidator());
		setLabelOfComponent(password, "passwordLabel");
		password.setRequired(!existingPerson);
		password.setResetPassword(false);

		userForm.add(password);

		PasswordTextField repeatPasswordField = new PasswordTextField("repeatPasswordField", new PropertyModel<String>(
				this, "repeatedPassword"));
		setLabelOfComponent(repeatPasswordField, "passwordLabel2");
		repeatPasswordField.setRequired(!existingPerson);
		repeatPasswordField.setResetPassword(false);

		userForm.add(new EqualPasswordInputValidator(password, repeatPasswordField));

		userForm.add(repeatPasswordField);
	}

	private void buildDiverCheck() {
		userForm.add(new CheckBox("diverCheck", new PropertyModel<Boolean>(this, "registerDiver")).setEnabled(false));
	}

	private void buildDiveGuideCheck() {
		CheckBox diveGuideCheck = new CheckBox("diveGuideCheck", new PropertyModel<Boolean>(this, "registerDiveGuide"));

		diveGuideCheck.add(new AjaxEventBehavior("onchange") {

			private static final long serialVersionUID = 1L;

			@Override
			protected void onEvent(AjaxRequestTarget target) {
				currentDivingSchoolContainer.setVisible(!currentDivingSchoolContainer.isVisible());
				target.add(currentDivingSchoolContainer);
			}
		});
		userForm.add(diveGuideCheck);
	}

	private void buildCurrentDivingSchoolContainer() {
		// Container for DiveGuide checkbox
		currentDivingSchoolContainer = new WebMarkupContainer("currentDivingSchoolContainer");
		currentDivingSchoolContainer.setOutputMarkupPlaceholderTag(true);
		currentDivingSchoolContainer.setVisible(false);
		userForm.add(currentDivingSchoolContainer);

		currentDivingSchoolContainer.add(new TextField<String>("currentDivingSchool", new PropertyModel<String>(this,
				"currentDivingSchool")));
	}

	private void buildCaptchaPanel() {
		userForm.add(new Captcha("captchaPanel"));
	}

	public void setLabelOfComponent(FormComponent<?> component, String label) {
		component.setLabel(new ApostrophResourceModel(label));
	}

	public String getRepeatedPassword() {
		return repeatedPassword;
	}

	public void setRepeatedPassword(String repeatedPassword) {
		this.repeatedPassword = repeatedPassword;
	}

	public boolean isRegisterDiver() {
		return registerDiver;
	}

	public void setRegisterDiver(boolean registerDiver) {
		this.registerDiver = registerDiver;
	}

	public boolean isRegisterDiveGuide() {
		return registerDiveGuide;
	}

	public void setRegisterDiveGuide(boolean registerDiveGuide) {
		this.registerDiveGuide = registerDiveGuide;
	}

	public String getCurrentDivingSchool() {
		return currentDivingSchool;
	}

	public void setCurrentDivingSchool(String currentDivingSchool) {
		this.currentDivingSchool = currentDivingSchool;
	}
}